﻿using System.Collections.Generic;
using TestBat.ViewModels.Attributes;
using TestBat.ViewModels.Base;
using System.Windows.Controls;

namespace TestBat.IViewModels.Base
{
    public abstract class ListViewModel<I, C> : ViewModel, IListViewModel<I, C>
        where I : IListItemViewModel
        where C : ICollection<I>
    {

        public ListViewModel(bool checkUnsavedChanges)
        {
            this.items = default(C);
            this.selected = default(I);
            this.checkUnsavedChanges = checkUnsavedChanges;
        }

        public C Items
        {
            get
            {
                if (items == null)
                    items = RI();

                return items;
            }
            private set
            {
                items = value;

                NotifyPropertyChanged(() => this.Items);
            }
        }

        public I Selected
        {
            get { return selected; }
            set
            {
                if ((selected == null && value != null) || (selected != null && !selected.Equals(value)))
                {
                    if (checkUnsavedChanges)
                        ChangeSelectedWithCheck(selected, value);
                    else
                        ChangeSelectedWithoutCheck(selected, value);
                }

                NotifyPropertyChanged(() => Selected);
            }
        }

        [CheckUnsavedChanges]
        private void ChangeSelectedWithCheck(I from, I to)
        {
            ChangeSelected(from, to);
        }

        private void ChangeSelectedWithoutCheck(I from, I to)
        {
            ChangeSelected(from, to);
        }

        protected virtual void ChangeSelected(I from, I to)
        {
            if (from != null && !from.Equals(to))
                from.OnLostFocus();

            selected = to;
        }

        public void RecreateItems()
        {
            Items = RI();
        }

        [BusinessErrorDialog]
        private C RI()
        {
            return _RecreateItems();
        }

        protected abstract C _RecreateItems();

        private readonly bool checkUnsavedChanges;

        private C items;
        private I selected;
    }
}
